'''
Created on 10/10/2013

@author: daniel
'''
import arista
import colecciones.listaEnlazada
import unittest
import vertice


class Grafo(object):
    '''
    Clase que asocia a Vertice y a Arista
    '''
    def __init__(self):
        self.__vertices__=colecciones.listaEnlazada.ListaEnlazada()
    
    def agregarVertice(self, vertice): #Agrega un vertice al Grafo.
        vertice.setPosicion(self.__vertices__.getTamanio())
        self.__vertices__.agregar(vertice, self.__vertices__.getTamanio())#lo agrega al final
    
    def eliminarVertice(self, vertice): #Elimina el vertice del Grafo. En caso que el vertice tenga conexiones con otros vertices, se eliminan todas sus conexiones.
        if(self.__vertices__.incluye(vertice)==False):return None
        i=j=0
        while (i<self.__vertices__.getTamanio()):
            if(self.__vertices__.elemento(i).getListaDeAdyacentes().incluye(vertice)==True):
                self.desConectar(self.__vertices__.elemento(i), vertice)
            if(self.__vertices__.elemento(i).__cmp__(vertice)==0):j=i
            i+=1
        return self.__vertices__.eliminar(j)
    
    def conectar(self, origen, destino, peso): #Conecta el vertice origen con el vertice destino con peso.
        origen.getListaDeAdyacentes().agregar(arista.Arista(destino,peso),origen.getListaDeAdyacentes().getTamanio())
    
    def desConectar(self, origen, destino): #Desconecta el vertice origen con el destino.
        j=None
        i=0
        while(i<origen.getListaDeAdyacentes().getTamanio()):
            if(origen.getListaDeAdyacentes().elemento(i).getVerticeDestino().__cmp__(destino)==0):
                j=i
                i=origen.getListaDeAdyacentes().getTamanio()
            i+=1
        if j is None:return None
        else : return origen.getListaDeAdyacentes().eliminar(j)
    
    def getListaDeVertices(self):#Retorna la lista con todos los vertices del grafo.
        return self.__vertices__
    
    def vertice(self, posicion): #Retorna el vertice dada su posicion.
        return self.__vertices__.elemento(posicion)

class Test(unittest.TestCase):


    def testName(self):
        self.assertIsInstance(Grafo(), Grafo, "Testea la correcta creacion")
        
    def testAgregarVertice(self):
        first=Grafo()
        self.assertTrue(first.__vertices__.esVacia(), "Verifica grafo Vacio")
        first.agregarVertice(vertice.Vertice(314,colecciones.listaEnlazada.ListaEnlazada(),9635))
        self.assertEquals(first.__vertices__.elemento(0).getDato(),314,"Testea fake-vertice correctamente aniadido")
    
    def testEliminarVertice(self):
        first=Grafo()
        self.assertTrue(first.__vertices__.esVacia(), "Verifica grafo Vacio")
        unVertice=vertice.Vertice(314,colecciones.listaEnlazada.ListaEnlazada(),0)
        first.agregarVertice(unVertice)
        self.assertEquals(first.__vertices__.elemento(0),unVertice,"Testea elemento correctamente aniadido")
        first.eliminarVertice(unVertice)
        self.assertTrue(first.__vertices__.esVacia(), "Verifica grafo Vacio")
        
    
    def testConectar(self):
        first=Grafo()
        self.assertTrue(first.__vertices__.esVacia(), "Verifica grafo Vacio")
        unVertice=vertice.Vertice(314,colecciones.listaEnlazada.ListaEnlazada(),first.__vertices__.getTamanio())
        first.agregarVertice(unVertice)
        self.assertEquals(first.__vertices__.elemento(0),unVertice,"Testea vertice correctamente aniadido")
        otroVertice=vertice.Vertice(315,colecciones.listaEnlazada.ListaEnlazada(),first.__vertices__.getTamanio())
        first.agregarVertice(otroVertice)
        self.assertEquals(first.__vertices__.elemento(1),otroVertice,"Testea vertice correctamente aniadido")
        self.assertTrue(first.__vertices__.elemento(0).getListaDeAdyacentes().esVacia(), "Verifica existencia de adyacente")
        first.conectar(unVertice, otroVertice,5)#los conecta con peso 5
        self.assertFalse(first.__vertices__.elemento(0).getListaDeAdyacentes().esVacia(), "Verifica existencia de adyacente")
        self.assertEquals(first.__vertices__.elemento(0).getListaDeAdyacentes().elemento(0).getVerticeDestino(),otroVertice, "Verifica existencia de adyacente")
    
    def testDesconectar(self):
        first=Grafo()
        self.assertTrue(first.__vertices__.esVacia(), "Verifica grafo Vacio")
        unVertice=vertice.Vertice(314,colecciones.listaEnlazada.ListaEnlazada(),first.__vertices__.getTamanio())
        first.agregarVertice(unVertice)#agrega un vertice al grafo first
        self.assertEquals(first.__vertices__.elemento(0),unVertice,"Testea vertice correctamente aniadido")
        otroVertice=vertice.Vertice(315,colecciones.listaEnlazada.ListaEnlazada(),first.__vertices__.getTamanio())
        first.agregarVertice(otroVertice)#agrega otro vertice al grafo first
        self.assertEquals(first.__vertices__.elemento(1),otroVertice,"Testea vertice correctamente aniadido")
        otroVertice1=vertice.Vertice(316,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice1)#agrega otro vertice al grafo first
        self.assertEquals(first.__vertices__.elemento(2),otroVertice1,"Testea vertice correctamente aniadido")
        otroVertice2=vertice.Vertice(31,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice2)#agrega otro vertice al grafo first
        self.assertEquals(first.__vertices__.elemento(3),otroVertice2,"Testea vertice correctamente aniadido")
        
        self.assertTrue(first.__vertices__.elemento(0).getListaDeAdyacentes().esVacia(), "Ningun vertice esta conectado")
        '''
        a partir de aqui conecta y desconecta unVertice con otroVertice2
        '''
        first.conectar(unVertice, otroVertice2,5)#los conecta con peso 5
        self.assertFalse(first.__vertices__.elemento(0).getListaDeAdyacentes().esVacia(), "Verifica existencia de adyacente")
        self.assertEquals(first.__vertices__.elemento(0).getListaDeAdyacentes().elemento(0).getVerticeDestino(),otroVertice2, "Verifica existencia de adyacente")
        
        arista=first.desConectar(unVertice, otroVertice2)
        self.assertEquals(arista.getVerticeDestino(),otroVertice2,"Verifica que se elimino la arista correcta")
        self.assertTrue(first.__vertices__.elemento(0).getListaDeAdyacentes().esVacia(), "Verifica No existencia de adyacente")
        '''
        a partir de aqui conecta y desconecta otroVertice1 con otroVertice
        '''
        first.conectar(otroVertice1, otroVertice,65)#los conecta con peso 5
        self.assertFalse(first.__vertices__.elemento(2).getListaDeAdyacentes().esVacia(), "Verifica existencia de adyacente")
        self.assertEquals(first.__vertices__.elemento(2).getListaDeAdyacentes().elemento(0).getVerticeDestino(),otroVertice, "Verifica existencia de adyacente")
        
        arista=first.desConectar(otroVertice1, otroVertice)
        self.assertEquals(arista.getVerticeDestino(),otroVertice,"Verifica que se elimino la arista correcta")
        self.assertTrue(first.__vertices__.elemento(2).getListaDeAdyacentes().esVacia(), "Verifica No existencia de adyacente")

    
    def testGetListaDeVertices(self):
        first=Grafo()
        
        unVertice=vertice.Vertice(314,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(unVertice)#agrega un vertice al grafo first
        otroVertice=vertice.Vertice(315,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice)#agrega otro vertice al grafo first
        otroVertice1=vertice.Vertice(316,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice1)#agrega otro vertice al grafo first
        otroVertice2=vertice.Vertice(31,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice2)#agrega otro vertice al grafo first

        lista=first.getListaDeVertices()
        self.assertEquals(lista.elemento(0).getDato(), 314,"Verifica primer vertice de la lista")
        self.assertEquals(lista.elemento(1).getDato(), 315,"Verifica segundo vertice de la lista")
        self.assertEquals(lista.elemento(2).getDato(), 316,"Verifica tercer vertice de la lista")
        self.assertEquals(lista.elemento(3).getDato(), 31,"Verifica cuarto vertice de la lista")
    
    def testVertice(self):
        first=Grafo()
        unVertice=vertice.Vertice(314,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(unVertice)#agrega un vertice al grafo first
        otroVertice=vertice.Vertice(315,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice)#agrega otro vertice al grafo first
        otroVertice1=vertice.Vertice(316,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice1)#agrega otro vertice al grafo first
        otroVertice2=vertice.Vertice(31,colecciones.listaEnlazada.ListaEnlazada())
        first.agregarVertice(otroVertice2)#agrega otro vertice al grafo first
        
        self.assertEquals(first.vertice(0), unVertice, "Verifica correcta devolucion del vertice segun la posicion")
        self.assertEquals(first.vertice(1), otroVertice, "Verifica correcta devolucion del vertice segun la posicion")
        self.assertEquals(first.vertice(2), otroVertice1, "Verifica correcta devolucion del vertice segun la posicion")
        self.assertEquals(first.vertice(3), otroVertice2, "Verifica correcta devolucion del vertice segun la posicion")
        

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()